package com.dhecp.common.utils.barcode;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.awt.*;

public final class BarcodeUtil {
	
	public static void main(String[] args) {
		String fileDir = "D:/data/test";
		String fileName = "test.png";
		BufferedImage barCodeImage = createImg("PD886221223001", 500, 200);
		createBarcodeImgFile(barCodeImage, fileDir, fileName);
	}
	
	/**
	 * 存入文件
	 *
	 * @param barCodeImage
	 * @return 文件名
	 */
	public static String createBarcodeImgFile(BufferedImage barCodeImage, String fileDir, String fileName) {
	    boolean isWrite = false;
	    File file = new File(fileDir, fileName);
	    try {
		    file.createNewFile();
	        FileOutputStream outputStream = new FileOutputStream(file);
	        isWrite = ImageIO.write(barCodeImage, "png", outputStream);
	    } catch (IOException e) {
	        e.printStackTrace();
	        return null;
	    }

	    if (isWrite) {
		    return fileDir + "/" + fileName;
	    } else {
		    return null;
	    }
	}
	
	/**
	 * 生成简单条形码（无文字）
	 *
	 * @param content
	 * @param width
	 * @param height
	 * @return
	*/
	public static BufferedImage createImg(String content, int width, int height) {
	    // 定义位图矩阵BitMatrix
	    BitMatrix matrix = null;

	    try {
	        // 定义二维码参数
	        Map<EncodeHintType, Object> hints = new HashMap<>(3);
	        // 设置编码
	        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
	        // 设置容错等级
	        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
	        // 设置边距，默认为5
	        hints.put(EncodeHintType.MARGIN, 3);

	        // 使用code_128格式进行编码生成条形码
	        MultiFormatWriter writer = new MultiFormatWriter();
	        matrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hints);
	    } catch (WriterException e) {
	        e.printStackTrace();
	        //throw new RuntimeException("条形码内容写入失败");
	    }

	    return MatrixToImageWriter.toBufferedImage(matrix);
	}

	
	/**
	 * 生成条形码（含文字）
	 * ****************************************************
	 * ----------------------------------------------
	 * |                         2023-06-10 10:55   |
	 * |                                            |
	 * |            商品名称 /超出不显示/              |
	 * |                                            |
	 * |    | || ||| | || |||| | | | ||| | | ||     |
	 * |    | || ||| | || |||| | | | ||| | | ||     |
	 * |    | || ||| | || |||| | | | ||| | | ||     |
	 * |    | || ||| | || |||| | | | ||| | | ||     |
	 * |               13800000000                  |
	 * ----------------------------------------------
	 * ===================================================
	 * 1、日期：顶部右侧
	 * 2、商品名称：居中
	 * 3、条形码：商品名称下方，且居中
	 * 4、条码内容：条形码下方，且居中
	 * *****************************************************
	 *
	 * @param codeImage     条形码图片
	 * @param bottomStr     底部文字
	 * @param titleStr      标题文字
	 * @param topRightStr   右上角文字
	 * @param pictureWidth  图片宽度
	 * @param pictureHeight 图片高度
	 * @param margin        边距
	 * @param fontSize      字体大小
	 * @return 条形码图片
	 */
	private static BufferedImage createWithWords(
	    BufferedImage codeImage,
	    String bottomStr,
	    String titleStr,
	    String topRightStr,
	    int pictureWidth,
	    int pictureHeight,
	    int margin,
	    int fontSize) {
	    BufferedImage picImage = new BufferedImage(pictureWidth, pictureHeight, BufferedImage.TYPE_INT_RGB);

	    Graphics2D g2d = picImage.createGraphics();
	    // 抗锯齿
	    setGraphics2D(g2d);
	    // 设置白色
	    setColorWhite(g2d, picImage.getWidth(), picImage.getHeight());

	    // 条形码默认居中显示
	    int codeStartX = (pictureWidth - codeImage.getWidth()) / 2;
	    int codeStartY = (pictureHeight - codeImage.getHeight()) / 2 + 2 * margin;
	    // 画条形码到新的面板
	    g2d.drawImage(codeImage, codeStartX, codeStartY, codeImage.getWidth(), codeImage.getHeight(), null);

	    // 给条码上下各画一条线
	    // 设置颜色
	    g2d.setColor(Color.LIGHT_GRAY);
	    int y1 = 2 * margin + codeImage.getHeight();
	    int y2 = 2 * margin + 2 * codeImage.getHeight();
	    g2d.drawLine(0, y1, pictureWidth, y1);
	    g2d.drawLine(0, y2, pictureWidth, y2);

	    // 画文字到新的面板
	    g2d.setColor(Color.BLACK);
	    // 字体、字型、字号
	    g2d.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));
	    // 文字与条形码之间的间隔
	    int wordAndCodeSpacing = 3;

	    // 底部文字（居中）
	    if (StringUtils.isNotEmpty(bottomStr)) {
	        // 文字长度
	        int strWidth = g2d.getFontMetrics().stringWidth(bottomStr);
	        // 文字X轴开始坐标
	        int strStartX = (pictureWidth - strWidth) / 2;
	        if (strStartX < margin) {
	            strStartX = margin;
	        }
	        // 文字Y轴开始坐标
	        int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing;
	        // 画文字
	        g2d.drawString(bottomStr, strStartX, strStartY);
	    }

	    // 右上角文字
	    if (StringUtils.isNotEmpty(topRightStr)) {
	        // 文字长度
	        int strWidth = g2d.getFontMetrics().stringWidth(topRightStr);
	        // 文字X轴开始坐标
	        int strStartX = pictureWidth - strWidth - margin;
	        // 文字Y轴开始坐标
	        int strStartY = margin + fontSize;
	        // 画文字
	        g2d.drawString(topRightStr, strStartX, strStartY);
	    }

	    // 标题文字（居中）
	    if (StringUtils.isNotEmpty(titleStr)) {
	    	if (titleStr.length() > 11) {
	            titleStr = titleStr.substring(0, 11);
	        }
	        // 字体、字型、字号
	        int fs = (int) Math.ceil(fontSize * 1.5);
	        g2d.setFont(new Font("宋体", Font.PLAIN, fs));
	        // 文字长度
	        int strWidth = g2d.getFontMetrics().stringWidth(titleStr);
	        // 文字X轴开始坐标
	        int strStartX = (pictureWidth - strWidth) / 2;
	        if (strStartX < margin) {
	            strStartX = margin;
	        }
	        // 文字Y轴开始坐标
	        int strStartY = codeStartY - margin;
	        // 画文字
	        g2d.drawString(titleStr, strStartX, strStartY);
	    }

	    g2d.dispose();
	    picImage.flush();

	    return picImage;
	}
	
	/**
	 * 设置 Graphics2D 属性 （抗锯齿）
	 *
	 * @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
	 */
	private static void setGraphics2D(Graphics2D g2d) {
	    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
	    g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
	    Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
	    g2d.setStroke(s);
	}

	/**
	 * 设置背景为白色
	 *
	 * @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
	 */
	private static void setColorWhite(Graphics2D g2d, int width, int height) {
	    g2d.setColor(Color.WHITE);
	    // 填充整个屏幕
	    g2d.fillRect(0, 0, width, height);
	    // 设置笔刷
	    g2d.setColor(Color.BLACK);
	}

}
